module ProcessQueue.Core exposing (..)
import Html as H
import Html.Attributes as A
import ProcessQueue.Queue as Q
import ProcessQueue.Model exposing (..)
import ProcessQueue.Acc as Acc
import ProcessQueue.Writter exposing (..)


type Msg 
  = Noop

empty_model : Model
empty_model = Model Q.mock_queue 0 (Acc 0 0) "Nothing to print"

mock_model : Model
mock_model = Model Q.mock_queue 0 (Acc 0 0) "Nothing to print"



view : Model -> H.Html Msg
view model =
  H.div
    []
    [ H.div [ A.id "work-room" ] [Q.view (.queue model)]
    , pointer_view (.pointer model) 
    ]

pointer_view : Pointer -> H.Html Msg
pointer_view p = 
  let class = 
    case p of
      0 -> "pointer1"
      1 -> "pointer2"
      2 -> "pointer3"
      _ -> "pointer1"
  in 
    H.div 
      [A.id "pointer",A.class class] []


with_new_pcb : Model -> PCB -> Model
with_new_pcb model pcb =
 {model | queue = (Q.with_new_process (.queue model) pcb)}

-- 每次处理的起点
tick : Model -> Model
tick model =
 let ((Writter result logs) as writter) = (return model) >>= process_point_pcb >>= acc_inc >>= adjust_point_pcb >>= adjust_pointer
 in  {result | print = print_log "; " writter}


-- 增加新进程
on_pcb_add : Model -> PCB -> Model
on_pcb_add model pcb =
 let new_model = with_new_pcb model pcb 
 in case .pointer new_model of
   0 -> new_model
   _ -> { new_model 
        | pointer = 0
        , acc = Q.new_acc 0
        }


-- 处理指针指向的第一个pcb
process_point_pcb : Model -> Writter Model
process_point_pcb model = 
 let queue = Q.process (.pointer model) (.queue model)
 in Writter {model | queue = queue} ["process_point_pcb: " ++ Q.show queue]
 
 

-- 进程计步器+1
acc_inc : Model -> Writter Model
acc_inc model =
 let acc = Acc.inc_acc (.acc model)
 in Writter {model | acc = acc} ["acc_inc: " ++ Acc.show acc]

-- 调整指针指向的第一个pcb
adjust_point_pcb : Model -> Writter Model
adjust_point_pcb model =
 let (queue,complete_queue,acc) = adjusted_queue (.pointer model) (.queue model) [] (.acc model)
 in 
  Writter
    { model 
    | queue = queue
    , acc = acc
    }
    ["调整指针指向的pcb: " ++ Q.show queue]

-- TODO: TEST
-- 调整指针
adjust_pointer : Model -> Writter Model
adjust_pointer model = 
  let new_pointer = adjusted_pointer (.pointer model) (.queue model)
      new_model =  
        case (.pointer model) == new_pointer of
          True -> {model | pointer = new_pointer }
          False -> { model 
                   | pointer = new_pointer
                   , acc = Q.new_acc new_pointer 
                   }
  in  Writter new_model ["调整指针，等待测试"]

adjusted_pointer : Pointer -> Queue -> Pointer
adjusted_pointer p q =
  if Q.is_pointing_empty p q then
    if Q.is_pointing_last p q then 0
    else p+1
  else p

-- TODO: TEST
-- 指针指向的第一个pcb调整好后的队列
adjusted_queue : Int -> Queue -> List a -> Acc -> (Queue,List a,Acc)
adjusted_queue pointer queue _ acc = 
  if (Q.is_point_pcb_completed pointer queue) then
    let (_,new_queue) = Q.remove_point_pcb pointer queue
        new_acc               = Acc.clear_acc acc
    in  (new_queue,[],new_acc)

  else if Acc.is_max acc then
    let new_queue = Q.point_pcb_down pointer queue
        new_acc   = Acc.clear_acc acc
    in  (new_queue,[],new_acc)

  else (queue,[],acc)